// GePoint3dSet.cpp: implementation of the GePoint3dSet class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "GePoint3dSet.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

void GePoint3dExtent::UnionWith( const GePoint3dExtent& totherExt, GePoint3dSet& theSet ) const
{
	theSet.RemoveExtentAll();
	IntersectState is = IntersectStateWith( totherExt );
	if ( is == eEqual ) theSet.AddExtentDirectly( *this );
	if ( is == eIn ) theSet.AddExtentDirectly( totherExt );
	if ( is == eBeIn ) theSet.AddExtentDirectly( *this );
	if ( is == eLeftOut )
	{
		theSet.AddExtentDirectly( totherExt );
		theSet.AddExtentDirectly( *this );
	}
	if ( is == eRightOut )
	{
		theSet.AddExtentDirectly( *this );
		theSet.AddExtentDirectly( totherExt );
	}
	if ( is == eLeftInter || is == eRightInter )
	{
		DblSet setX, setY, setZ;
		m_XExt.UnionWith( totherExt.m_XExt, setX );
		m_YExt.UnionWith( totherExt.m_YExt, setY );
		m_ZExt.UnionWith( totherExt.m_ZExt, setZ );

		for ( int i = 0; i < setX.GetExtentCount(); i++ )
		{
			for ( int j = 0; j < setY.GetExtentCount(); j++ )
			{
				for ( int k = 0; k < setZ.GetExtentCount(); k++ )
				{
					GePoint3dExtent aExt;
					aExt.XExtent( setX.GetExtentAt( i ) );
					aExt.YExtent( setY.GetExtentAt( j ) );
					aExt.ZExtent( setZ.GetExtentAt( k ) );
					theSet.AddExtentDirectly( aExt );
				}
			}
		}
	}
}

GePoint3dExtent GePoint3dExtent::IntersectionWith( const GePoint3dExtent& totherExt ) const
{
	IntersectState is = IntersectStateWith( totherExt );
	if ( is == eEqual || is == eBeIn ) return *this;
	if ( is == eIn ) return totherExt;
	if ( is == eLeftInter || is == eRightInter )
	{
		DblExtent extX, extY, extZ;
		extX = m_XExt.IntersectionWith( totherExt.m_XExt );
		extY = m_YExt.IntersectionWith( totherExt.m_YExt );
		extZ = m_ZExt.IntersectionWith( totherExt.m_ZExt );
		
		if ( !extX.IsEmpty() && !extY.IsEmpty() && !extZ.IsEmpty() )
		{
			GePoint3dExtent aExt;
			aExt.XExtent( extX );
			aExt.YExtent( extY );
			aExt.ZExtent( extZ );
			return aExt;
		}
	}

	return GePoint3dExtent();
}

void GePoint3dExtent::DifferenceWith( const GePoint3dExtent& totherExt, GePoint3dSet& theSet ) const
{
	theSet.RemoveExtentAll();
	IntersectState is = IntersectStateWith( totherExt );
	if ( is == eLeftOut || is == eRightOut ) theSet.AddExtentDirectly( *this );
	if ( is == eIn || is == eLeftInter || is == eRightInter )
	{
		DblSet setX, setY, setZ;
		m_XExt.DifferenceWith( totherExt.m_XExt, setX );
		m_YExt.DifferenceWith( totherExt.m_YExt, setY );
		m_ZExt.DifferenceWith( totherExt.m_ZExt, setZ );

		GePoint3dExtent aExt;
		if ( setX.GetExtentCount() == 0 )
		{
			aExt.XExtent( m_XExt );
			if ( setY.GetExtentCount() == 0 )
			{
				aExt.YExtent( m_YExt );
				if ( setZ.GetExtentCount() == 0 )
					return;
				else
				{
					for ( int k = 0; k < setZ.GetExtentCount(); k++ )
					{
						aExt.ZExtent( setZ.GetExtentAt( k ) );
						theSet.AddExtentDirectly( aExt );
					}
					return;
				}
			}
			else
			{
				for ( int j = 0; j < setY.GetExtentCount(); j++ )
				{
					for ( int k = 0; k < setZ.GetExtentCount(); k++ )
					{
						aExt.YExtent( setY.GetExtentAt( j ) );
						aExt.ZExtent( setZ.GetExtentAt( k ) );
						theSet.AddExtentDirectly( aExt );
					}
				}
			}
		}
		else
		{
			for ( int i = 0; i < setX.GetExtentCount(); i++ )
			{
				aExt.XExtent( setX.GetExtentAt( i ) );
				if ( setY.GetExtentCount() == 0 )
				{
					aExt.YExtent( m_YExt );
					if ( setZ.GetExtentCount() == 0 )
					{
						aExt.ZExtent( m_ZExt );
						theSet.AddExtentDirectly( aExt );
					}
					else
					{
						for ( int k = 0; k < setZ.GetExtentCount(); k++ )
						{
							aExt.ZExtent( setZ.GetExtentAt( k ) );
							theSet.AddExtentDirectly( aExt );
						}
					}
				}
				else
				{
					for ( int j = 0; j < setY.GetExtentCount(); j++ )
					{
						aExt.YExtent( setY.GetExtentAt( j ) );
						if ( setZ.GetExtentCount() == 0 )
						{
							aExt.ZExtent( m_ZExt );
							theSet.AddExtentDirectly( aExt );
						}
						else
						{
							for ( int k = 0; k < setZ.GetExtentCount(); k++ )
							{
								aExt.ZExtent( setZ.GetExtentAt( k ) );
								theSet.AddExtentDirectly( aExt );
							}
						}
					}
				}
			}
		}
	}
}

void GePoint3dSet::UnionByCollection( const GePoint3dCollection& aClt )
{
}

void GePoint3dSet::UnionByExtent( const GePoint3dExtent& aExt )
{
	if ( IsEmpty() )
	{
		AddExtentDirectly( aExt );
		return;
	}

	GePoint3dExtent::IntersectState is;
	for ( int i = 0; i < GetExtentCount(); i++ )
	{
		is = aExt.IntersectStateWith( GetExtentAt( i ) );
		if ( is == GePoint3dExtent::eEqual || is == GePoint3dExtent::eBeIn )
			return;
		else if ( is == GePoint3dExtent::eIn )
			RemoveExtentAt( i-- );
	}

	for ( i = 0; i < GetExtentCount(); i++ )
	{
		is = aExt.IntersectStateWith( GetExtentAt( i ) );
		if ( is == GePoint3dExtent::eLeftInter )
		{
			if ( i < GetExtentCount() - 1 && ( is = aExt.IntersectStateWith( GetExtentAt( i + 1 ) ) ) == GePoint3dExtent::eRightInter )
			{
				GePoint3dExtent theExt;
				theExt.SetBounds( GetExtentAt( i ).LowerBound(), GetExtentAt( i + 1 ).UpperBound() );
				SetExtentAt( i, theExt );
				RemoveExtentAt( i + 1 );
				return;
			}
			else
			{
				GePoint3dExtent theExt;
				theExt.SetBounds( GetExtentAt( i ).LowerBound(), aExt.UpperBound() );
				SetExtentAt( i, theExt );
				return;
			}
		}
		else if ( is == GePoint3dExtent::eRightInter )
		{
			if ( i > 0 && ( is = aExt.IntersectStateWith( GetExtentAt( i - 1 ) ) ) == GePoint3dExtent::eLeftInter )
			{
				GePoint3dExtent theExt;
				theExt.SetBounds( GetExtentAt( i - 1 ).LowerBound(), GetExtentAt( i ).UpperBound() );
				SetExtentAt( i, theExt );
				RemoveExtentAt( i - 1 );
				return;
			}
			else
			{
				GePoint3dExtent theExt;
				theExt.SetBounds( aExt.LowerBound(), GetExtentAt( i - 1 ).UpperBound() );
				SetExtentAt( i, theExt );
				return;
			}
		}
	}

	for ( i = 0; i < GetExtentCount(); i++ )
	{
		if ( aExt.UpperBound() < GetExtentAt( i ).LowerBound() )
		{
			InsertExtentAt( i, aExt );
			return;
		}
	}

	AddExtentDirectly( aExt );
}

void GePoint3dSet::IntersectionByExtent( const GePoint3dExtent& aExt )
{
	if ( IsEmpty() )
		return;

	GePoint3dSet aSet;
	GePoint3dExtent theExt;
	for ( int i = 0; i < GetExtentCount(); i++ )
	{
		theExt = aExt.IntersectionWith( GetExtentAt( i ) );
		if ( !theExt.IsEmpty() )
			aSet.AddExtentDirectly( theExt );
	}
	
	*this = aSet;
}

void GePoint3dSet::DifferenceByExtent( const GePoint3dExtent& aExt )
{
	if ( IsEmpty() )
		return;

	GePoint3dSet aSet;
	GePoint3dSet theSet;
	for ( int i = 0; i < GetExtentCount(); i++ )
	{
		GetExtentAt( i ).DifferenceWith( aExt, aSet );
		if ( !aSet.IsEmpty() )
			theSet.AddSetDirectly( aSet );
	}
	
	*this = theSet;
}

void GePoint3dSet::UnionBy( const GePoint3dSet& totherSet )
{
	if ( totherSet.IsEmpty() ) 
		return;

	if ( IsEmpty() )
	{
		*this = totherSet;
		return;
	}

	for ( int i = 0; i < totherSet.GetExtentCount(); i++ )
	{
		UnionByExtent( totherSet.GetExtentAt( i ) );
	}
}

void GePoint3dSet::IntersectionBy( const GePoint3dSet& totherSet )
{
	if ( IsEmpty() )
		return;

	if ( totherSet.IsEmpty() )
	{
		MakeEmpty();
		return;
	}

	GePoint3dSet theSet;
	for ( int i = 0; i < totherSet.GetExtentCount(); i++ )
	{
		GePoint3dSet aSet( *this );
		aSet.IntersectionByExtent( totherSet.GetExtentAt( i ) );
		theSet.UnionBy( aSet );
	}

	*this = theSet;
}

void GePoint3dSet::DifferenceBy( const GePoint3dSet& totherSet )
{
	if ( IsEmpty() || totherSet.IsEmpty() )
		return;

	for ( int i = 0; i < totherSet.GetExtentCount(); i++ )
	{
		DifferenceByExtent( totherSet.GetExtentAt( i ) );
	}
}